﻿using System;

namespace UnityEngine.UI
{
    /// <summary>
    /// 根据文本内容自适应尺寸
    /// </summary>
    [RequireComponent(typeof(RectTransform))]
    public class UITextSizeFitterEx : MonoBehaviour
    {
        [SerializeField]
        public Text FitterText;
        [SerializeField]
        public float HorizontalOffset = 10;
        [SerializeField]
        public float VerticalOffset = 10;

        public float MaxTextWidth = 635f;

        public bool FitterHeightOnly = false;

        private RectTransform _rectTrans;

        private bool _hasInit = false;
        private string _lastStr;
        private Vector2 _lastSize;

        private void InitComponent()
        {
            _rectTrans = transform as RectTransform;
            _lastStr = FitterText.text;
            _lastSize = Vector2.zero;

            FitterText.horizontalOverflow = HorizontalWrapMode.Wrap;
            FitterText.verticalOverflow = VerticalWrapMode.Overflow;
            FitterText.rectTransform.sizeDelta = new Vector2(MaxTextWidth, FitterText.fontSize + 2);
            _hasInit = true;
        }

        public void Awake()
        {
            if (!_hasInit) InitComponent();
            Refresh();
        }

        private void OnValidate()
        {
            if (!_hasInit) InitComponent();
            Refresh();
        }

        public void Update()
        {
            if (_lastStr == FitterText.text) return;

            Vector2 preferredSize = GetTextPreferredSize();
            if (_lastSize != preferredSize)
            {
                Refresh();
            }
        }

        public void RefreshImmediate()
        {
            Refresh();
        }

        protected void Refresh()
        {
            _lastStr = FitterText.text;

            Vector2 preferredSize = GetTextPreferredSize();
            _lastSize = preferredSize;

            Vector2 v = _rectTrans.sizeDelta;
            v.y = preferredSize.y + VerticalOffset;


            if (!FitterHeightOnly)
            {
                v.x = preferredSize.x + HorizontalOffset;
            }

            _rectTrans.sizeDelta = v;

            if (OnRectSizeChanged != null)
                OnRectSizeChanged.Invoke(v);
        }

        private Vector2 GetTextPreferredSize()
        {
            float width = Mathf.Min(FitterText.preferredWidth, MaxTextWidth);
            float height = FitterText.preferredHeight;
            return new Vector2(width, height);
        }

        Action<Vector2> OnRectSizeChanged;
        public UITextSizeFitterEx WaitSizeChanged(Action<Vector2> on)
        {
            this.OnRectSizeChanged = on;
            return this;
        }
    }
}